/*
 * @Author: wuqingchun
 * @Date: 2024-06-29 16:53:11
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-06-29 20:51:03
 */

#include "http_error.h"
#include "http_parser.h"

int32_t CHTTPParser::OnRecv(IHTTPEvent& refEvent, HTTP_BUF_S& refBuf)
{
    char* pcCur;
    char cCur;

    for (pcCur = refBuf.pcStart; pcCur < refBuf.pcEnd; pcCur++)
    {
        cCur = *pcCur;
        switch (m_enState)
        {
        /* HTTP methods: GET, HEAD, POST */
        case EnumHTTPParserState::ST_START:
        {
            m_szMethod[m_ulMethodIndex++] = cCur;

            if (cCur == HTTP_PARSER_CR || cCur == HTTP_PARSER_LF) 
            {
                break;
            }

            if ((cCur < 'A' || cCur > 'Z') && cCur != '_' && cCur != '-') 
            {
                return HTTP_PARSE_INVALID_METHOD;
            }
            
            m_enState = EnumHTTPParserState::ST_METHOD;
            break;
        }
        case EnumHTTPParserState::ST_METHOD:
        {
            if (cCur == ' ') 
            {
                switch (m_ulMethodIndex) {
                case 3:
                    if (http_str3_cmp(m_szMethod, 'G', 'E', 'T', ' ')) {
                        m_uiMethod = HTTP_METHOD_GET;
                        break;
                    }

                    if (http_str3_cmp(m_szMethod, 'P', 'U', 'T', ' ')) {
                        m_uiMethod = HTTP_METHOD_PUT;
                        break;
                    }

                    break;

                case 4:
                    if (m_szMethod[1] == 'O') {

                        if (http_str3Ocmp(m_szMethod, 'P', 'O', 'S', 'T')) {
                            m_uiMethod = HTTP_METHOD_POST;
                            break;
                        }

                        if (http_str3Ocmp(m_szMethod, 'C', 'O', 'P', 'Y')) {
                            m_uiMethod = HTTP_METHOD_COPY;
                            break;
                        }

                        if (http_str3Ocmp(m_szMethod, 'M', 'O', 'V', 'E')) {
                            m_uiMethod = HTTP_METHOD_MOVE;
                            break;
                        }

                        if (http_str3Ocmp(m_szMethod, 'L', 'O', 'C', 'K')) {
                            m_uiMethod = HTTP_METHOD_LOCK;
                            break;
                        }

                    } else {

                        if (http_str4cmp(m_szMethod, 'H', 'E', 'A', 'D')) {
                            m_uiMethod = HTTP_METHOD_HEAD;
                            break;
                        }
                    }

                    break;

                case 5:
                    if (http_str5cmp(m_szMethod, 'M', 'K', 'C', 'O', 'L')) {
                        m_uiMethod = HTTP_METHOD_MKCOL;
                        break;
                    }

                    if (http_str5cmp(m_szMethod, 'P', 'A', 'T', 'C', 'H')) {
                        m_uiMethod = HTTP_METHOD_PATCH;
                        break;
                    }

                    if (http_str5cmp(m_szMethod, 'T', 'R', 'A', 'C', 'E')) {
                        m_uiMethod = HTTP_METHOD_TRACE;
                        break;
                    }

                    break;

                case 6:
                    if (http_str6cmp(m_szMethod, 'D', 'E', 'L', 'E', 'T', 'E')) {
                        m_uiMethod = HTTP_METHOD_DELETE;
                        break;
                    }

                    if (http_str6cmp(m_szMethod, 'U', 'N', 'L', 'O', 'C', 'K')) {
                        m_uiMethod = HTTP_METHOD_UNLOCK;
                        break;
                    }

                    break;

                case 7:
                    if (http_str7_cmp(m_szMethod, 'O', 'P', 'T', 'I', 'O', 'N', 'S', ' '))
                    {
                        m_uiMethod = HTTP_METHOD_OPTIONS;
                    }

                    break;

                case 8:
                    if (http_str8cmp(m_szMethod, 'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D'))
                    {
                        m_uiMethod = HTTP_METHOD_PROPFIND;
                    }

                    break;

                case 9:
                    if (http_str9cmp(m_szMethod,
                            'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H'))
                    {
                        m_uiMethod = HTTP_METHOD_PROPPATCH;
                    }

                    break;
                }

                m_enState = EnumHTTPParserState::ST_SPACES_BEFORE_URI;
                break;
            }

            if ((cCur < 'A' || cCur > 'Z') && cCur != '_' && cCur != '-') {
                return HTTP_PARSE_INVALID_METHOD;
            }

            m_szMethod[m_ulMethodIndex++] = cCur;

            break;
        }
        
        default:
            break;
        }
    }

    refEvent.Send(refBuf);

    return HTTP_OK;
}